package cn.songdragon.zboschina.proxy;

import java.time.LocalDateTime;
import java.util.Iterator;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.locks.ReentrantLock;

import org.apache.http.HttpHost;

import cn.songdragon.zboschina.proxy.config.Config;

public class ProxyHost {

	private HttpHost proxy;
	/**
	 * 4XX,5XX计数
	 */
	private int failCount;
	/**
	 * 200计数
	 */
	private int succCount;
	/**
	 * 2XX,3XX计数
	 */
	private int emptyCount;
	private ReentrantLock lock = new ReentrantLock();

	private BlockingQueue<RequestRecord> requests = new LinkedBlockingQueue<>();

	private ProxyHost() {
		this.failCount = 0;
	}

	/**
	 * 默认http协议
	 * 
	 * @param hostname
	 * @param port
	 */
	public ProxyHost(String hostname, int port) {
		this();
		this.proxy = new HttpHost(hostname, port);
	}

	public ProxyHost(String hostname, int port, String scheme) {
		this();
		this.proxy = new HttpHost(hostname, port, scheme);
	}

	public HttpHost getProxy() {
		return proxy;
	}

	public void setProxy(HttpHost proxy) {
		this.proxy = proxy;
	}

	public int getFailCount() {
		return failCount;
	}

	// public void setFailCount(int failCount) {
	// this.lock.lock();
	// this.failCount = failCount;
	// this.lock.unlock();
	// }

	public void increaseFailCount() {
		this.lock.lock();
		this.failCount++;
		this.lock.unlock();
	}

	public void decreaseFailCount() {
		this.lock.lock();
		this.failCount--;
		this.lock.unlock();
	}

	public void resetFailCount() {
		this.lock.lock();
		this.failCount = 0;
		this.lock.unlock();
	}

	public void increaseSuccCount() {
		this.lock.lock();
		this.succCount++;
		this.lock.unlock();
	}

	public void increaseEmptyCount() {
		this.lock.lock();
		this.emptyCount++;
		this.lock.unlock();
	}

	public void resetCount() {
		this.lock.lock();
		this.emptyCount = this.emptyCount / 3;
		this.succCount = this.succCount / 3;
		this.failCount = this.failCount / 3;
		this.lock.unlock();
	}

	@Override
	public int hashCode() {
		return this.proxy.hashCode();
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		ProxyHost other = (ProxyHost) obj;
		if (proxy == null) {
			if (other.proxy != null)
				return false;
		} else if (!proxy.equals(other.proxy))
			return false;
		return true;
	}

	@Override
	public String toString() {
		return "ProxyHost [proxy=" + proxy + ", failCount=" + failCount + ", succCount=" + succCount + ", emptyCount="
				+ emptyCount + "]";
	}

	public void addRequestConfig(RequestRecord requestRecord) {
		this.requests.add(requestRecord);
	}

	public boolean isAvaliable() {
		LocalDateTime now = LocalDateTime.now();
		LocalDateTime oneMinAgo = now.minusMinutes(Config.minute);
		this.lock.lock();
		Iterator<RequestRecord> it = requests.iterator();
		while (it.hasNext()) {
			RequestRecord r = it.next();
			if (r.dateTime.isBefore(oneMinAgo)) {
				it.remove();
			}
		}
		boolean isAvaliable = false;
		if (this.requests.size() < Config.rate && this.failCount == 0) {
			isAvaliable = true;
		}

		this.lock.unlock();
		return isAvaliable;
	}

	public int getSuccCount() {
		return succCount;
	}

	public void setSuccCount(int succCount) {
		this.succCount = succCount;
	}

	public void setFailCount(int failCount) {
		this.failCount = failCount;
	}

}
